#include "sessionmanager.h"

#include "../documents/icontainerdocument.h"
#include "../documents/idocument.h"
#include "../persistence/ipersistenceassistant.h"
#include "../persistence/ipersistentdocument.h"
#include "../persistence/istorage.h"
#include "../persistence/persistence.h"
#include "../sessions/isessionprovider.h"

#include <QtCore/QFile>
#include <QtCore/QDataStream>
#include <QtCore/QUrl>
#include <QtGui/QApplication>

using namespace core;

SessionManager* sessionManager = 0;

SessionManager* SessionManager::getInstance()
{
    if (sessionManager == 0)
    {
        sessionManager = new SessionManager();
    }

    return sessionManager;
}

void SessionManager::destroy()
{
    delete sessionManager;
    sessionManager = 0;
}

void SessionManager::setSessionProvider(ISessionProvider* sessionProvider)
{
    m_sessionProvider = sessionProvider;
}

SessionManager::SessionManager() : QObject(),
    m_sessionProvider(0),
    m_projects(),
    m_documents()
{

}

SessionManager::~SessionManager()
{

}

QSharedPointer<IPersistenceAssistant>
    SessionManager::getNativeAssistant(
        const QSharedPointer<IDocument>& document) const
{
    QList<QSharedPointer<IPersistenceAssistant> > assistants =
        Persistence::getNativeAssistants(document);

    QSharedPointer<IPersistenceAssistant> assistant;

    foreach (const QSharedPointer<IPersistenceAssistant>& _assistant,
        assistants)
    {
        if (!_assistant->getPersistentDocument().isNull())
        {
            assistant = _assistant;
            break;
        }
        else
        {
            Persistence::closeAssistant(_assistant);
        }
    }

    return assistant;
}

QSharedPointer<IPersistenceAssistant> SessionManager::getNativeAssistant(
        const QString& perDocument, const QString& storage) const
{
    QSharedPointer<IPersistenceAssistant> ret;

    const QSharedPointer<IPersistentDocument> _perDocument =
        Persistence::createDocument(perDocument, storage);

    const QSharedPointer<IPersistenceAssistant> assistant =
        Persistence::getNativeAssistant(_perDocument);

    if (!assistant->getDocument().isNull())
    {
        ret = assistant;
    }

    return ret;
}

void SessionManager::persist()
{
    const QString appPath = qApp->applicationDirPath();

    QFile file(appPath + "//swp.session");
    file.open(QIODevice::WriteOnly);

    QDataStream stream(&file);
    stream.setVersion(QDataStream::Qt_4_7);

    stream << m_projects;

    stream << m_documents;

    file.close();
}

void SessionManager::clearSession()
{
    m_projects.clear();
    m_documents.clear();
}

void SessionManager::writeProjectToSession(const QString& url,
    const QString& storage)
{
    m_projects.append(QString("%1|%2").arg(url).arg(storage));
}

void SessionManager::writeDocumentToSession(const QString& url,
    const QString& storage)
{
    m_documents.append(QString("%1|%2").arg(url).arg(storage));
}

void SessionManager::restoreSession()
{
    clearSession();

    if (m_sessionProvider != 0)
    {
        const QString appPath = qApp->applicationDirPath();

        QFile file(appPath + "//swp.session");
        file.open(QIODevice::ReadOnly);

        QDataStream stream(&file);
        stream.setVersion(QDataStream::Qt_4_7);

        stream >> m_projects;
        stream >> m_documents;

        foreach (const QString& project, m_projects)
        {
            const QStringList split = project.split("|",
                QString::SkipEmptyParts);

            Q_ASSERT(split.size() == 2); // bad serialization

            m_sessionProvider->openProject(split.first(), split.last());
        }

        foreach (const QString& document, m_documents)
        {
            const QStringList split = document.split("|",
                QString::SkipEmptyParts);

            Q_ASSERT(split.size() == 2); // bad serialization

            const QSharedPointer<IPersistenceAssistant> assistant =
                getNativeAssistant(split.first(), split.last());

            if (!assistant.isNull())
            {
                m_sessionProvider->openDocument(assistant->getDocument());
            }
        }
    }
}

void SessionManager::persistSession()
{
    clearSession();

    if (m_sessionProvider != 0)
    {
        const QList<QSharedPointer<IDocument> > documents =
            m_sessionProvider->openedDocuments();

        foreach (const QSharedPointer<IDocument>& document,
            documents)
        {
            const QSharedPointer<IPersistenceAssistant> assistant =
                getNativeAssistant(document);

            if (!assistant.isNull())
            {
                if (document->isContainer())
                {
                    writeProjectToSession(
                        assistant->getPersistentDocument()->url().toString(),
                        assistant->getPersistentDocument()->storage(
                            )->registeredName());
                }
                else
                {
                    writeDocumentToSession(
                        assistant->getPersistentDocument()->url().toString(),
                        assistant->getPersistentDocument()->storage(
                            )->registeredName());
                }
            }
        }
    }

    persist();
}
